package gob.cgr.sgrh.ejb.session;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.persistence.Query;
import javax.persistence.TemporalType;
import javax.validation.ValidationException;

import gob.cgr.sgrh.ejb.entidad.ActaEntrega;
import gob.cgr.sgrh.ejb.entidad.CumplimientoDocumentacion;
import gob.cgr.sgrh.ejb.entidad.Legajo;
import gob.cgr.sgrh.ejb.entidad.MovimientoDePersonal;
import gob.cgr.sgrh.ejb.entidad.Persona;
import gob.cgr.sgrh.ejb.entidad.Personal;
import gob.cgr.sgrh.ejb.entidad.SolicitudDocumento;
import gob.cgr.sgrh.ejb.entidad.SolicitudLegajo;
import gob.cgr.sgrh.ejb.local.PersonalDAO;

@Local
@Stateless
public class PersonalSession extends GenericSessionImpl<Personal, Integer>
		implements PersonalDAO {

	@Override
	public Personal registrarPersonal(Personal object) {
		// TODO Auto-generated method stub
		System.out.println("registrar personal..");
		MovimientoDePersonal m=object.getMovimientoDePersonalList().get(0);
		object.setMovimientoDePersonalList(null);
		if (object.getIdPersona().getIdPersona() == null) {
			// persona no registrada
			
			System.out.println("persistiendo");
			getEm().persist(object.getIdPersona());
			
		
		}
		System.out.println("refreshing..");
		getEm().refresh(object.getIdPersona());
		System.out.println("colocando el codigo del personal..");
		object.setCodigoPersonal(generateId());
		object.setEstado("ACTIVO");
		System.out.println("ahora EJB id persona es " + object.getIdPersona());
		super.registrar(object);
		System.out.println("registrado el personal");
		getEm().refresh(object);
		m.setIdPersonal(object);
		System.out.println("idpersonal es "+object.getIdPersonal());
		actualizarMovimientoPersonal(m);
		System.out.println("persistido su primer movimiento");
		return object;

	}
	
	
	
	

	private String generateId() {
		Query q = getEm().createQuery(
				"select c from Personal c order by c.idPersonal desc");
		try {
			List<Object> o = q.setMaxResults(1).getResultList();
			for(Object ob:o){
				return String.format("%010d", ((Personal) ob).getIdPersonal() + 1);	
			}
		
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("error al generar el codigo "+e.getMessage());
		}
		return String.format("%010d", 1);

	}

	/**
	 * p : Clase Personal con sus datos basicos
	 */

	@Override
	public ArrayList<Personal> buscarPersonal(Personal p) {
		// TODO Auto-generated method stub
		
		Query q = getEm().createNamedQuery("Personal.findByDatosPersonales");
		q.setParameter("apaterno", "%" + p.getIdPersona().getApellidoPaterno()
				+ "%");
		q.setParameter("amaterno", "%" + p.getIdPersona().getApellidoMaterno()
				+ "%");
		q.setParameter("nombres", "%" + p.getIdPersona().getNombres() + "%");
		q.setParameter("codigoPersonal", "%" + p.getCodigoPersonal() + "%");
		q.setParameter("estado","%"+p.getEstado()+"%");
		
		return (ArrayList<Personal>) q.getResultList();
	}


	@Override
	public void registrarSolicitudDocumento(SolicitudDocumento sol) {
		// generamos el numero de solicitud
		Query q=getEm().createQuery("select c from SolicitudDocumento c order by c.idSolicitudDocumento desc");
		String numSol=null;
		try {
			List<Object> o = q.setMaxResults(1).getResultList();
			for(Object ob:o){
				numSol= String.format("%04d", ((SolicitudDocumento) ob).getIdSolicitudDocumento() + 1);	
			}
		
		} catch (Exception e) {
				//System.out.println("error al generar el codigo "+e.getMessage());
		}
		Date d=new Date();
		numSol=String.format("%1$tY%1$tm",d ) + (numSol==null?"0001":numSol);
		System.out.println("numero solicitud generada "+numSol);
		sol.setNumeroSolicitudDocu(numSol);
		sol.setEstado("P");//pendiente;
		sol.setFechaSolicitud(d);
		getEm().persist(sol);
		
	}
	@Override
	public SolicitudDocumento actualizarSolicitudDocumento(SolicitudDocumento sol) {
		System.out.println("actualizando la solicitud");
		if(sol.getEstado().equals("E")){
			sol.setNumeroDocumento(generarNumeroDocumento(sol));
			sol.setFechaAtendido(new Date());
			getEm().merge(sol);
		}
		else{
		getEm().merge(sol);
		}
		return sol;
	}
	
	
	private String generarNumeroDocumento(SolicitudDocumento s){
	Query q=getEm().createNamedQuery("SolicitudDocumento.listarUltimoNumeroGenerado");
		Calendar c=Calendar.getInstance();
		c.set(Calendar.DATE, 1);
		System.out.println("fecha "+c.getTime());
		q.setParameter("desde", c.getTime());
		q.setParameter("idDocumento", s.getTipoDocumento().getIdDocumento());
		List l=q.getResultList();
		String nro=String.format("%04d", (l.size()+1));
		System.out.println("numero de documento "+nro);
		return nro+"-"+c.get(Calendar.MONTH);
		
		
	}
	
	
	
	@Override
	public Personal buscarPersonalPorDNI(String dni) {
		Query q=getEm().createQuery("select c from Personal c where c.idPersona.nroDocumento=:dni");
		q.setParameter("dni",dni);
		Object o=q.getResultList();
		System.out.println("busqueda personal "+dni +" resultado "+o);
		
		return ((List<Personal>)o).size()>0?((List<Personal>)o).get(0):null;
	}
	@Override
	public List<SolicitudDocumento> listarSolicitudes(Integer idPersonal,
			Date desde, Date hasta, String estado) {
		estado=estado==null || estado.equals("")?"%":estado;
		Query q;
		if(idPersonal!=null){
			q=getEm().createNamedQuery("SolicitudDocumento.listarPorPersonalFechas");
			q.setParameter("idPersonal",idPersonal);
		}
		else
		{
			q=getEm().createNamedQuery("SolicitudDocumento.listarPorFechas");
		}
		
		q.setParameter("desde",desde,TemporalType.DATE);
		q.setParameter("hasta", hasta,TemporalType.DATE);
		q.setParameter("estado",estado);
		Object o=q.getResultList();
		System.out.println("listando "+o);
		return o==null?null:((List<SolicitudDocumento>)o);
	}
	
	@Override
	public List<CumplimientoDocumentacion> listarCumplimiento(Persona p) {
		// TODO Auto-generated method stub
	Query q=getEm().createNamedQuery("CumplimientoDocumentacion.findByIdPersona");
		q.setParameter("idPersona",p.getIdPersona());
		Object o=q.getResultList();
		return o==null?new ArrayList<CumplimientoDocumentacion>():((List<CumplimientoDocumentacion>)o);
		
	}
	@Override
	public void actualizarCumplimientoDocumentacion(
			List<CumplimientoDocumentacion> documentacion) {
		// TODO Auto-generated method stub
		Date d=new Date();
		for(CumplimientoDocumentacion c:documentacion){
						
			if(c.getIdCumplimientoDoc()!=null){
				if(c.getOk()==false){ //este cumplimiento ya existia pero el usuario lo desmarco, entonces se elimina
					getEm().remove(getEm().merge(c));
				}
				
			}
			else{
				//si no posee un Id, entonces no existe en BD, pero solo se debe ingresar si tiene el check verificado
				if(c.getOk()){
				c.setFechaPresentacion(d);// la fecha actual	
				getEm().persist(c);
				}
			}
			}
		}
	
	@Override
	public List<MovimientoDePersonal> listarMovimientosPersonal(
			Integer idPersonal) {
		System.out.println("listando los movimientos...");
		Query q=getEm().createNamedQuery("MovimientoDePersonal.listarPorPersonal");
		q.setParameter("idPersonal",idPersonal);
		Object o=q.getResultList();
		System.out.println("obtenido los movimientos:"+o);
		return o==null?new ArrayList<MovimientoDePersonal>() :((List<MovimientoDePersonal>)o);
		
	}
	
	@Override
	public void actualizarMovimientoPersonal(MovimientoDePersonal movimiento) {
		// TODO Auto-generated method stub
		List<MovimientoDePersonal> mov=listarMovimientosPersonal(movimiento.getIdPersonal().getIdPersonal());
		if(movimiento.getIdMovimientoPersonal()==null){
			if(mov.size()>0){
				System.out.println("actualizando el movimiento previo");
				mov.get(0).setSalida(movimiento.getIngreso());
				//getEm().merge(mov.get(0))
			}
			getEm().persist(movimiento);
		}
		else{
			getEm().merge(movimiento);
		}
		
	}


	@Override
	public List<Legajo> listarLegajoPersonal(Integer idPersonal,
			Integer seccionLegajo) {
		System.out.println("llamando lista legajo");
		Query q=getEm().createNamedQuery("Legajo.listarPorPersonalSeccion");
		q.setParameter("seccion",seccionLegajo);
		q.setParameter("idPersonal",idPersonal);
		Object o=q.getResultList();
		return o==null?new ArrayList<Legajo>():((List<Legajo>)o);
	}
	
	@Override
	public void actualizarLegajo(Legajo legajo) {
	
			if(legajo.getIdLegajo()==null){
				getEm().persist(legajo);
			}
			else{
				getEm().merge(legajo);
			}
		
	}
	
	private void generarNumeroLegajo(Legajo legajo){
		//legajo.get
		int len=legajo.getIdPersonal().getCodigoPersonal().length();
		String numero="S-"+legajo.getIdSeccionLegajo().getNumero()+"-"+legajo.getIdPersonal().getCodigoPersonal().substring(len-4,len);
		legajo.setNumeroDoc(numero);
	}
	
	@Override
	public void eliminarLegajo(Legajo legajo) {
		// TODO Auto-generated method stub
		System.out.println("en EJB eliminando el legajo...");
		getEm().remove(getEm().merge(legajo));
		System.out.println("en EJB eliminado el legajo");
	}
	
	@Override
	public Legajo obtenerLegajo(Integer idLegajo) {
		
		return getEm().find(Legajo.class, idLegajo);
	}
	
	@Override
	public void actualizarCumplimientoDocumentacion(
			CumplimientoDocumentacion c) {
		Date d=new Date();
		if(c.getIdCumplimientoDoc()!=null){
			if(c.getOk()==false){ //este cumplimiento ya existia pero el usuario lo desmarco, entonces se elimina
				c.setFechaPresentacion(null);
				getEm().remove(getEm().merge(c));
			}
			
		}
		else{
			//si no posee un Id, entonces no existe en BD, pero solo se debe ingresar si tiene el check verificado
			if(c.getOk()){
			c.setFechaPresentacion(d);// la fecha actual	
			getEm().persist(c);
			
			}
		
		}
	}
	
	@Override
	public void solicitarActualizarLegajo(SolicitudLegajo s, Legajo l) {
		// TODO Auto-generated method stub
		if(s.getIdSolicitudLegajo()==null){
		s.setFechaRealizada(new Date());
		s.setEstado("P");
		getEm().persist(s);
		getEm().flush();
		System.out.println("colocando la idsolicitud Generada:"+s.getIdSolicitudLegajo());
		l.setIdSolicitud(s.getIdSolicitudLegajo());
		actualizarLegajo(l);
		}
		
	}
	
	@Override
	public void eliminarSolicitudLegajo(SolicitudLegajo s) {
		// TODO Auto-generated method stub
		Query q=getEm().createNamedQuery("Legajo.findByIdSolicitud");
		q.setParameter("idSolicitud",s.getIdSolicitudLegajo());
		List o=q.getResultList();
		Legajo le=o!=null && o.size()>0?(Legajo)o.get(0):null;
					
		if(le!=null){
		//Legajo l=getEm().find(Legajo.class,s.getIdLegajo());
		System.out.println("intentando elimina la solicitud del legajo "+le.isChecked());
		if(le.isChecked()==false && "P".equals(s.getEstado())){
		getEm().remove(getEm().merge(le));
		getEm().remove(getEm().merge(s));
		}
		else{
			System.out.println("No puede eliminar la solicitud porque ya esta atendida");
			throw new javax.validation.ValidationException("Solo puede eliminar un solicitud cuando esta Pendiente");
			
		}
		}
		else{
			System.out.println("removiendo solamente la solicitud");
			getEm().remove(getEm().merge(s));
		}
		
	}
	@Override
	public List<SolicitudLegajo> listarSolicitudesDeLegajo(Integer idPersonal,
			Date desde, Date hasta, String estado) {
		//listarSolicitudLegajo
		estado=estado==null || estado.equals("")?"%":estado;
		Query q;
				q=getEm().createNamedQuery("SolicitudLegajo.listarSolicitudLegajo");
		
		q.setParameter("idPersonal", idPersonal);
		q.setParameter("desde",desde,TemporalType.DATE);
		q.setParameter("hasta", hasta,TemporalType.DATE);
		q.setParameter("estado",estado);
		Object o=q.getResultList();
		System.out.println("listando solicitudes de legajo "+o);
		return o==null?null:((List<SolicitudLegajo>)o);
	
	}
	@Override
	public SolicitudLegajo obtenerSolicitudLegajo(Integer idSolicitudLegajo) {
		Query q=getEm().createNamedQuery("SolicitudLegajo.findByIdSolicitudLegajo");
		q.setParameter("idSolicitudLegajo",idSolicitudLegajo);
		SolicitudLegajo sol=null;
		for(Object s:q.getResultList()){
			sol=(SolicitudLegajo)s;
			break;
		}
		
		
		return sol;
	}
	@Override
	public void actualizarSolicitudLegajo(SolicitudLegajo s) {
		// TODO Auto-generated method stub
		getEm().merge(s);
	}
	
	@Override
	public List<ActaEntrega> listarActasEntregas(Integer idPersonal,
			Date desde, Date hasta, String estado) {
		estado=estado==null || estado.equals("")?"%":estado;
		Query q;
		//if(idPersonal==null){
		//q=getEm().createQuery("SELECT a FROM ActaEntrega a WHERE a.fechaRegistro between  :desde and :hasta and estado like :estado");
		//}else{
		q=getEm().createNamedQuery("ActaEntrega.listarActasPorPersonalFechas");
		q.setParameter("idPersonal", idPersonal);
		//}
		
		q.setParameter("desde",desde,TemporalType.DATE);
		q.setParameter("hasta", hasta,TemporalType.DATE);
		q.setParameter("estado",estado);
		List<ActaEntrega> l=q.getResultList();
		System.out.println("actas de entregas "+l);
		return l;
	}

	@Override
	public ActaEntrega obtenerActaEntrega(Integer idActaEntrega) {
		// TODO Auto-generated method stub
		return getEm().find(ActaEntrega.class, idActaEntrega);
	}





	@Override
	public ActaEntrega registrarActaEntrega(ActaEntrega acta) {
		// TODO Auto-generated method stub
		Query q=getEm().createQuery("select a from ActaEntrega a where a.idPersonal.idPersonal=:idPersonal and a.estado='P'");
		q.setParameter("idPersonal",acta.getIdPersonal().getIdPersonal());
		if(q.getResultList().size()>0){
			System.out.println("El personal ya tiene un acta en proceso");
			throw new ValidationException("El personal ya tiene un acta en proceso");
		}
		else{
			acta.setEstado("P");
			acta.setFechaRegistro(new Date());
		acta.setNumeroActa(generarNroActaEntrega());
		getEm().persist(acta);
		}
		return acta;
	}

	private String generarNroActaEntrega(){
		Query q = getEm().createQuery(
				"select c from ActaEntrega c order by c.idActaEntrega desc");
		try {
			List<Object> o = q.setMaxResults(1).getResultList();
			for(Object ob:o){
				return String.format("%05d", ((ActaEntrega) ob).getIdActaEntrega() + 1);	
			}
		
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("error al generar el codigo "+e.getMessage());
		}
		return String.format("%05d", 1);
		//return "";
	}



	@Override
	public ActaEntrega actualizarActaEntrega(ActaEntrega acta) {
		// TODO Auto-generated method stub
		System.out.println("acta ok"+acta.isActaOk());
		acta.setEstado(acta.isActaOk()?"C":acta.getEstado());
		getEm().merge(acta);
		return acta;
	}
	
	@Override
	public void eliminarActaEntrega(ActaEntrega acta) {
		// TODO Auto-generated method stub
		getEm().remove(getEm().merge(acta));
	}
}
